package com.bosch.in.rtp1.ept.action;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.List;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.json.JSONArray;
import net.sf.json.JSONSerializer;

import org.apache.log4j.Logger;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.MappingDispatchAction;

import com.bosch.in.rtp1.ept.action.form.ReleasedHoldCriteriaForm;
import com.bosch.in.rtp1.ept.constant.CommonConstants;
import com.bosch.in.rtp1.ept.constant.FilterParameter;
import com.bosch.in.rtp1.ept.constant.HoldCodeType;
import com.bosch.in.rtp1.ept.constant.TableType;
import com.bosch.in.rtp1.ept.manager.DurationColorConManager;
import com.bosch.in.rtp1.ept.manager.FrozenColumnManager;
import com.bosch.in.rtp1.ept.manager.HoldCodeFilterManager;
import com.bosch.in.rtp1.ept.manager.ReleasedHoldManager;
import com.bosch.in.rtp1.ept.model.dto.DurationColorCon;
import com.bosch.in.rtp1.ept.model.dto.HoldCodeFilter;
import com.bosch.in.rtp1.ept.model.dto.JqgridJsonData;
import com.bosch.in.rtp1.ept.model.dto.ReleasedHold;
import com.bosch.in.rtp1.ept.model.technical.Condition4ReleasedHold;
import com.bosch.in.rtp1.ept.util.ConverterUtility;
import com.bosch.in.rtp1.ept.util.HoldCodeUtility;
import com.bosch.in.rtp1.ept.util.ManagerFactory;
import com.bosch.in.rtp1.ept.util.SQLConditionBuilder;
import com.bosch.in.rtp1.ept.util.StringUtility;
 
/**
 * The action class acts like a controller which will delegate to LotStatus manager class to 
 * do functionalities and then format returned data in kind of client supporting  
 * @author TPR1HC
 *
 */
public class ReleasedHoldAction extends MappingDispatchAction{
 
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private static final Logger LOGGER = Logger.getLogger(ReleasedHoldAction.class);
    /**
     * report template file to export to excel
     */
    private static final String EXCEL_TEMPLATE_FILE = "templates/releasedhold_template.xls";
    
    /**
     * report designer file to export to pdf
     */
    private static final String PDF_DESIGNER_FILE = "templates/releasedhold.jasper";
    
    
    /**
	 * Response to ajax call from Jquery grid, it will delegate to Manager class
	 * to query LotStatus according to search criteria in request parameter.
	 * The returned list then will be transformed to JSON format in order to 
	 * display on client side.
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return
     * @throws SQLException 
	 */
	public ActionForward displayReleasedHold(ActionMapping mapping,ActionForm form,
			HttpServletRequest request,HttpServletResponse response) throws SQLException 
			 {
		LOGGER.debug("Begin displayReleasedHold");
		// get HoldCodeFilterManager instance
    	HoldCodeFilterManager holdCodeFilterManager = ManagerFactory.getInstance().getHoldCodeFilterManager();
    	
    	/* query all HoldCode filter values */
    	List<HoldCodeFilter> holdCodeFilters = holdCodeFilterManager.getHoldCodeFilters(HoldCodeType.HC);
    	((ReleasedHoldCriteriaForm)form).setHoldCodes(holdCodeFilters);
    	
    	// get HoldCodeFilterManager instance
    	holdCodeFilterManager = ManagerFactory.getInstance().getHoldCodeFilterManager();
    	/* query all HoldCode classified filter values */
    	holdCodeFilters = holdCodeFilterManager.getHoldCodeFilters(HoldCodeType.HC_RECLASF);
    	// Handle special Hold Code
    	HoldCodeUtility.injectAllHCForRest(holdCodeFilters);
    	((ReleasedHoldCriteriaForm)form).setHoldCodesReclassified(holdCodeFilters);
    	
    	// get FrozenColumnManager instance
    	FrozenColumnManager frozenColumnManager =  ManagerFactory.getInstance().getFrozenColumnManager();
    	List<String> frzCols = frozenColumnManager.getFrozenColumns(TableType.RELEASED_HOLD);
    	
    	// create duration color condition manager instance
		DurationColorConManager durColConManager = ManagerFactory.getInstance().getDurationColorConManager();
		
		// load durationColorCondition conditions
		DurationColorCon durColCon = durColConManager.getDuratonColCon();
    	
    	request.setAttribute(CommonConstants.RELEASED_HOLD_FRZ_COLS, frzCols);
    	request.setAttribute(CommonConstants.RED_COLOR_CON, StringUtility.buildRedColorCondition(durColCon));
    	request.setAttribute(CommonConstants.YELLOW_COLOR_CON, StringUtility.buildYellowColorCondition(durColCon));
    	
    	
    	LOGGER.debug("End displayReleasedHold");
    	// Forward to form page
        return mapping.findForward("success");
	}
    
    
	/**
	 * Response to ajax call from Jquery grid, it will delegate to Manager class
	 * to query LotStatus according to search criteria in request parameter.
	 * The returned list then will be transformed to JSON format in order to 
	 * display on client side.
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return
	 * @throws ParseException 
	 * @throws SQLException 
	 * @throws IOException 
	 */
	@SuppressWarnings("unchecked")
	public ActionForward search(ActionMapping mapping,ActionForm form,
			HttpServletRequest request,HttpServletResponse response) throws ParseException, SQLException, IOException 
			 {
		LOGGER.debug("Begin search");
		
		// build search condition from parameters in request
		Condition4ReleasedHold searchCriteria = SQLConditionBuilder.extractReleasedHoldParameters(request);
    	// get ReleasedHoldManager instance
		ReleasedHoldManager releasedHoldManager = ManagerFactory.getInstance().getReleasedHoldManager();
    	
    	/* query data with search condition gotten from parameter in request */
    	List<ReleasedHold> releasedHolds = releasedHoldManager.getReleasedHolds(searchCriteria);
    	
    	/* total records */
    	int totalRecords = releasedHolds.size();
    	
    	// convert returned data in kind of JSON format which Jqgrid supports
    	JSONArray cellarray = ConverterUtility.convertToRH_JSONRows(releasedHolds);
    	JqgridJsonData jLotStatuses = new JqgridJsonData();
    	jLotStatuses.setPage(Integer.valueOf(request.getParameter(FilterParameter.PAGE)));
    	jLotStatuses.setRecords(totalRecords);
    	jLotStatuses.setRowNum(Integer.valueOf(request.getParameter(FilterParameter.ROW_NUM)));
    	jLotStatuses.setRows(cellarray);
    	
    	// write data to output stream with MIME type is text
    	//JSONSerializer serializer = new JSONSerializer();  
    	String jsonResponse = JSONSerializer.toJSON(jLotStatuses).toString();
    	response.setContentType("text/html;charset=utf-8");
    	response.setHeader("cache-control", "no-cache");
    	PrintWriter out = response.getWriter();
    	out.println(jsonResponse);
    	out.flush();
    	
    	LOGGER.debug("End search");
    	return null;
	}
	
	
		/**
	    * Receive JSON string from client, parsing it to releaseHold list 
	    * and update these values to databases
	    * @param mapping The ActionMapping used to select this instance
	    * @param form The optional ActionForm bean for this request (if any)
	    * @param request The HTTP request we are processing
	    * @param response The HTTP response we are creating
	    * @exception Exception if an exception occurs
	    * @return the ActionForward to forward control to
		 * @throws SQLException 
		 * @throws ParseException 
	    */
	   public ActionForward update(
	       ActionMapping mapping,
	       ActionForm form,
	       HttpServletRequest request,
	       HttpServletResponse response) throws SQLException, ParseException
	       {

			   LOGGER.debug("Begin update");
			   
			   // get ReleasedHoldManager instance
			   ReleasedHoldManager releasedHoldManager = ManagerFactory.getInstance().getReleasedHoldManager();
		    	
			   // get ReleaseHold list from request
			   List<ReleasedHold> rHList = ConverterUtility.convertToReleasedHolds(request);
		
			   releasedHoldManager.updateReleasedHolds(rHList);
			   
		       LOGGER.debug("End update");
		       
		       return null;
	   }
	
	/**
	 * Response to export to excel click, it will delegate to Manager class
	 * to query LotStatus according to search criteria in request parameter.
	 * The result list then will be save to excel file and returns to client
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return
	 * @throws ParseException 
	 * @throws SQLException 
	 * @throws IOException 
	 */
	public ActionForward exportExcel(ActionMapping mapping,ActionForm form,
			HttpServletRequest request,HttpServletResponse response) throws ParseException, SQLException, IOException 
			 {
		LOGGER.debug("Begin exportExcel");
		
		// build search condition from parameters in request
		Condition4ReleasedHold searchCriteria = SQLConditionBuilder.extractReleasedHoldParameters(request);
		
		// get template excel file which already pre-defined format and structure for content to populate
    	InputStream is = this.getServlet().getServletContext().getResourceAsStream(EXCEL_TEMPLATE_FILE);
		
    	// create duration color condition manager instance
		DurationColorConManager durColConManager = ManagerFactory.getInstance().getDurationColorConManager();
		
		// load durationColorCondition conditions
		DurationColorCon durColCon = durColConManager.getDuratonColCon();
    	
    	// get ReleasedHoldManager instance
    	ReleasedHoldManager releasedHoldManager = ManagerFactory.getInstance().getReleasedHoldManager();
    	
    	// query data and save the result to template excel file
		Workbook workbook = releasedHoldManager.exportToExcel(searchCriteria, is, durColCon);
		
    	// MIME type is excel
        response.setContentType("application/vnd.ms-excel");
        // offer the user the ability to download and save the resulting Excel file
        response.setHeader("Content-Disposition", "attachment; filename=ReleasedHold.xls");
    	ServletOutputStream out = response.getOutputStream();
    	workbook.write(out);
    	out.flush();
    	
    	LOGGER.debug("End exportExcel");
    	return null;
	}
	
	/**
	 * Response to export to pdf click, it will delegate to Manager class
	 * to query LotStatus according to search criteria in request parameter.
	 * The result list then will be save to pdf file and returns to client
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return
	 * @throws ParseException 
	 * @throws JRException 
	 * @throws SQLException 
	 * @throws IOException 
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public ActionForward exportPdf(ActionMapping mapping,ActionForm form,
			HttpServletRequest request,HttpServletResponse response) throws ParseException, SQLException, JRException, IOException 
			 {
		LOGGER.debug("Begin exportPdf");
		
		// build search condition from parameters in request
		Condition4ReleasedHold searchCriteria = SQLConditionBuilder.extractReleasedHoldParameters(request);
		
		// get ReleasedHoldManager instance
		ReleasedHoldManager releasedHoldManager = ManagerFactory.getInstance().getReleasedHoldManager();
		
		JasperPrint jasperPrint = releasedHoldManager.exportPdf(searchCriteria, this.getServlet().getServletContext().getResourceAsStream(PDF_DESIGNER_FILE));
		
		// MIME type is pdf
    	response.setContentType("application/pdf");
    	// offer the user the ability to download and save the resulting pdf file
    	response.setHeader("Content-Disposition", "attachment; filename=ReleasedHold.pdf");
		
		// stream out pdf content 
		ServletOutputStream servletOutputStream =response.getOutputStream();
    	JasperExportManager.exportReportToPdfStream(jasperPrint, servletOutputStream);
        servletOutputStream.flush();
        
        LOGGER.debug("End exportPdf");
        return null;
	}
}
